package com.mlog.njyjy.ndop.share.kafka.oauth.handler;

import com.mlog.njyjy.ndop.share.kafka.oauth.OauthBearerTokenJwt;
import com.mlog.njyjy.ndop.share.kafka.oauth.OauthRequest;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.security.auth.AuthenticateCallbackHandler;
import org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule;
import org.apache.kafka.common.security.oauthbearer.OAuthBearerValidatorCallback;
import org.apache.kafka.common.security.oauthbearer.internals.unsecured.OAuthBearerValidationResult;
import org.apache.kafka.common.utils.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.AppConfigurationEntry;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * .
 * </p>
 *
 * @author <a href="mailto:yingxiufeng@mlogcn.com">alex</a>
 * @version v1.0, 2020/7/13
 */
public class OauthAuthenticateValidatorCallbackHandler extends OauthAuthenticateBaseCallbackHandler {

    private final Logger log = LoggerFactory.getLogger(OauthAuthenticateValidatorCallbackHandler.class);

    private Time time = Time.SYSTEM;

    @Override
    public void configure(Map<String, ?> map, String saslMechanism, List<AppConfigurationEntry> jaasConfigEntries) {
        super.configure(map, saslMechanism, jaasConfigEntries);
    }

    private boolean isConfigured() {
        return this.configured;
    }

    @Override
    public void close() {

    }

    @Override
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        if (!isConfigured()) {
            throw new IllegalStateException("Callback handler not configured");
        }
        for (Callback callback : callbacks) {
            if (callback instanceof OAuthBearerValidatorCallback) {
                try {
                    OAuthBearerValidatorCallback validationCallback = (OAuthBearerValidatorCallback) callback;
                    handleCallback(validationCallback);
                } catch (KafkaException e) {
                    throw new IOException(e.getMessage(), e);
                }
            } else {
                throw new UnsupportedCallbackException(callback);
            }
        }
    }

    private void handleCallback(OAuthBearerValidatorCallback callback) {
        String accessToken = callback.tokenValue();
        if (accessToken == null) {
            throw new IllegalArgumentException("Callback missing required token value");
        }

        log.info("Trying to introspect Token!");
        OauthBearerTokenJwt token = oauthRequest.introspectToken(accessToken);
        log.info("Trying to introspected");

        // Implement Check Expire Token..
        long now = time.milliseconds();
        if (now > token.expirationTime()) {
            OAuthBearerValidationResult.newFailure("Expired Token, needs refresh!");
        }

        log.info("Validated! token..");
        callback.token(token);
    }
}
